package br.uece.tcc.fh.jxta;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Observable;
import java.util.Observer;

import br.uece.tcc.fh.jxta.controller.FhJxtaController;
import br.uece.tcc.fh.jxta.util.FhConstantes;

import net.jxta.discovery.DiscoveryEvent;
import net.jxta.discovery.DiscoveryListener;
import net.jxta.discovery.DiscoveryService;
import net.jxta.endpoint.Message;
import net.jxta.pipe.OutputPipe;
import net.jxta.pipe.PipeMsgEvent;
import net.jxta.pipe.PipeMsgListener;
import net.jxta.protocol.PipeAdvertisement;


/**
 * @author pedro
 *  
 */
public class FhMessenger extends Observable implements Runnable, PipeMsgListener, DiscoveryListener {
    public static int DEFAULT_THRESHOLD = 5; // limite de respostas de 1 peer
    private Hashtable observers = new Hashtable();

    public void addObserver(Observer observer) {
        observers.put(observer, observer);
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Runnable#run()
     */
    public void run() {
        long time = FhConstantes.CINCO_SEGUNDOS * 3;
        while (true) {
            try {
                // look for any peer
                DiscoveryService ds = FhJxtaController.getInstance().getFhBaseJxta().getDiscoveryService();
                if (ds != null) {
                    ds.getRemoteAdvertisements(null, DiscoveryService.ADV, null, null, DEFAULT_THRESHOLD, this);
                    ds.getRemoteAdvertisements(null, DiscoveryService.PEER, null, null, DEFAULT_THRESHOLD, this);
                    ds.getRemoteAdvertisements(null, DiscoveryService.GROUP, null, null, DEFAULT_THRESHOLD, this);
                    // wait a bit before sending a discovery message
                    if (time >= 5 * FhConstantes.UM_MINUTO) {
                        time = 5 * FhConstantes.UM_MINUTO;//estabiliza em 5 minutos
                    } else {
                        time *= 1.3;//aumenta em 30%
                    }
                    Thread.sleep(time);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see net.jxta.discovery.DiscoveryListener#discoveryEvent(net.jxta.discovery.DiscoveryEvent)
     */
    public void discoveryEvent(DiscoveryEvent arg0) {
        // TODO Auto-generated method stub

    }

    public void pipeMsgEvent(PipeMsgEvent evt) {
        receiveMessage(evt.getMessage());
    }

    public void receiveMessage(Message m) {
        System.out.println("Recebeu mensagem ...");
        try {
            FhMessage msg = new FhMessage(m);
            String message = msg.getMensagem();
            if (observers.size() > 0) {
                Enumeration en = observers.elements();
                while (en.hasMoreElements()) {
                    Observer observer = (Observer) en.nextElement();
                    observer.update(this, message);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendMessage(FhMessage msg, PipeAdvertisement pipeAdv) throws IOException {
        System.out.println("Enviado FhMessage para: " + pipeAdv.getName());
        OutputPipe out = FhJxtaController.getInstance().getFhBaseJxta().createOutputPipe(pipeAdv);
        out.send(msg.getMessage());
        out.close();
        System.out.println("Message sent to: " + pipeAdv.getName());
    }

}
